package com.yunquan.ohana.ui.scan

import android.content.Intent
import android.graphics.Color
import android.media.MediaPlayer
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.VibrationEffect
import android.os.Vibrator
import android.provider.MediaStore
import android.view.KeyEvent
import androidx.activity.result.contract.ActivityResultContracts
import com.google.zxing.BinaryBitmap
import com.google.zxing.ChecksumException
import com.google.zxing.FormatException
import com.google.zxing.NotFoundException
import com.google.zxing.RGBLuminanceSource
import com.google.zxing.common.HybridBinarizer
import com.google.zxing.qrcode.QRCodeReader
import com.journeyapps.barcodescanner.CaptureManager
import com.yunquan.ohana.BR
import com.yunquan.ohana.R
import com.yunquan.ohana.base.ui.BaseActivity
import com.yunquan.ohana.databinding.ActivityScanBinding
import com.yunquan.ohana.utils.FileUtils
import com.yunquan.ohana.utils.ImageUtils
import com.yunquan.ohana.utils.L
import com.yunquan.ohana.utils.ToastUtils
import java.io.File
import kotlin.random.Random


class ScanActivity : BaseActivity<ActivityScanBinding, ScanViewModel>() {
    private var mVibrator: Vibrator? = null
    private var capture: CaptureManager? = null

    override fun initContentView(savedInstanceState: Bundle?): Int {
        return R.layout.activity_scan
    }

    override fun initVariableId(): Int {
        return BR.scanViewModel
    }

    override fun initData(savedInstanceState: Bundle?) {
        super.initData(savedInstanceState)
        mVibrator = getSystemService(Vibrator::class.java)
        capture = CaptureManager(this, binding!!.zxingScanner)
        capture?.initializeFromIntent(intent, savedInstanceState)
        capture?.setShowMissingCameraPermissionDialog(true)
        capture?.decode()
        changeMaskColor()
    }

    override fun initViewObservable() {
        super.initViewObservable()

        binding!!.zxingScanner.decodeContinuous {
            result(it.text)
            capture?.onPause()
        }

        binding!!.llAlbum.setOnClickListener {
//            val intent = Intent(this, PhotosActivity::class.java)
            val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
            mAlbumResult.launch(intent)
        }
    }

    override fun onResume() {
        super.onResume()
        capture?.onResume()
    }

    override fun onPause() {
        super.onPause()
        mVibrator?.cancel()
        capture?.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
        capture?.onDestroy()
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        capture?.onSaveInstanceState(outState)
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        return binding!!.zxingScanner.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray, deviceId: Int) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId)
        capture?.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }

    private fun changeMaskColor() {
        val color: Int = Color.argb(100, Random.nextInt(256), Random.nextInt(256), Random.nextInt(256))
        binding!!.zxingScanner.viewFinder.setMaskColor(color)
    }

    private fun decodeQRCode(file: File?) {
        try {
            if (file == null || !file.exists()) {
                ToastUtils.showShort(R.string.file_does_not_exist)
                return
            }
            val bitmap = ImageUtils.decodeBitmap(file.absolutePath, 300, 300)
            if (bitmap == null) {
                ToastUtils.showShort(R.string.tip_read_file_failed)
                return
            }
            // 将图片转换成适合 ZXing 解析的格式
            val intArray = IntArray(bitmap.width * bitmap.height)
            bitmap.getPixels(intArray, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
            val rgbLuminanceSource = RGBLuminanceSource(bitmap.width, bitmap.height, intArray)
            val binaryBitmap = BinaryBitmap(HybridBinarizer(rgbLuminanceSource))

            // 使用 QRCodeReader 来解码
            val reader = QRCodeReader()
            val result = reader.decode(binaryBitmap)

            // 结果是二维码的内容
            val decodedText = result.text
            L.i("二维码内容: $decodedText")
            result(decodedText)
        } catch (e: NotFoundException) {
            e.printStackTrace()
            ToastUtils.showShort(R.string.no_qr_code_detected)
        } catch (e: ChecksumException) {
            e.printStackTrace()
            ToastUtils.showShort(R.string.qr_code_is_damaged_and_cannot_be_decoded)
        } catch (e: FormatException) {
            e.printStackTrace()
            ToastUtils.showShort(R.string.invalid_qr_code_format)
        } catch (e: Exception) {
            e.printStackTrace()
            ToastUtils.showShort(R.string.failed_to_decode_qr_code)
        }
    }

    // 相册选择返回
    private val mAlbumResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        // 这里处理返回结果
        if (result.resultCode == RESULT_OK) {
            result.data?.data?.let { uri ->
                val file = FileUtils.uriToFile(uri)
                decodeQRCode(file)
            }
        }
    }

    private fun result(text: String) {
        //播放声音、震动
        val mediaPlayer = MediaPlayer.create(this, R.raw.oh_qrcode)
        mediaPlayer.setOnCompletionListener {
            mediaPlayer.release()
        }
        mediaPlayer.start()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val vibrationEffect = VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE)
            mVibrator?.vibrate(vibrationEffect)
        } else {
            mVibrator?.vibrate(500)
        }
        Handler(Looper.getMainLooper()).postDelayed({
            val bundle = Bundle()
            bundle.putString("text", text)
            val intent = Intent()
            intent.putExtras(bundle)
            setResult(RESULT_CODE, intent)
            finish()
        }, 500)
    }

    companion object {
        const val RESULT_CODE = 10004
    }
}